#include <stdlib.h>
#include <stdio.h>

#include "ncurses.h"

#include "affichage.h"
#include "manipulation_cases.h"
#include "etat_partie.h"
#include "etat_bataille.h"
#include "ennemis.h"
#include "resume_saisie.h"
#include "etat_exploration.h"
#include "saisie_clavier_sdl.h"
#include "saisie_clavier_ncurses.h"
#include "tab_regions_accessibles.h"

#include "constantes_et_macros.h"






/**
 * \fn static char visible_par_joueur(const unsigned int x_elem, const unsigned int y_elem,
                                 const unsigned char taille_elem, const unsigned int x_j,
                                 const unsigned int y_j)
 * \brief Dit si un element d'une taille donnee, dont les coordonnees sont
 *        donnees par rapport a son coin superieur gauche, est dans le champ
 *        de vision du joueur ou non
 *
 * \param[in] x_elem Coordonnee horizontale de l'element
 * \param[in] y_elem Coordonnee verticales de l'element
 * \param[in] taille_elem Taille de l'element, en nombre de cases
 * \param[in] x_j Coordonnee horizontale du joueur
 * \param[in] y_j Coordonnee verticale du joueur
 * \return VRAI si l'element est visible, FAUX sinon
 *
 * \warning Les ennemis et projectiles, qui ont des tailles diverses, sont
 * reperes par les coordonnees de leur coin superieur gauche.\n
 * Le joueur, dont la taille est toujours de 3, est repere par son centre.
 */
static char visible_par_joueur(const unsigned int x_elem, const unsigned int y_elem,
                          const unsigned char taille_elem, const unsigned int x_j,
                          const unsigned int y_j)
{
    /*
     * attention : ne pas prendre des risques tels que des soustractions.
     * En effet, on travaille ici avec des unsigned, et
     * cela pourrait avoir des consequences desastreuses
     */

    if(x_elem + taille_elem + CHAMP_VISION_X > x_j &&
       y_elem + taille_elem + CHAMP_VISION_Y > y_j &&
       x_elem <= x_j + CHAMP_VISION_X &&
       y_elem <= y_j + CHAMP_VISION_Y)
    {
        return VRAI;
    }
    else
        return FAUX;
}



/**
 * \fn static void copier_carre(surface_jeu* ecran, const unsigned int x_dest,
                                const unsigned int y_dest, surface_jeu* surface_origine,
                                const unsigned int x_orig, const unsigned int y_orig,
                                const unsigned char taille)
 * \brief Copie une zone carree de cote 'taille' d'une surface a une autre
 *
 * \param[in,out] ecran La surface de destination
 * \param[in] x_dest Coordonnee horizontale, en pixels, de l'emplacement de destination
 * \param[in] y_dest Coordonnee verticale, en pixels, de l'emplacement de destination
 * \param[in] surface_origine La surface d'ou sera tire le carre
 * \param[in] x_orig Coordonnee horizontale, en pixels, de l'emplacement d'origine
 * \param[in] y_orig Coordonnee verticale, en pixels, de l'emplacement d'origine
 * \param[in] taille Nombre de pixels de cote du carre
 */
static void copier_carre(surface_jeu* ecran, const unsigned int x_dest,
                                const unsigned int y_dest, surface_jeu* surface_origine,
                                const unsigned int x_orig, const unsigned int y_orig,
                                const unsigned char taille)
{
    rectangle_pour_surface carre_dest;
    rectangle_pour_surface carre_orig;

    carre_dest.h = taille;
    carre_dest.w = taille;
    carre_dest.x = x_dest;
    carre_dest.y = y_dest;
    carre_orig.h = taille;
    carre_orig.w = taille;
    carre_orig.x = x_orig;
    carre_orig.y = y_orig;
    SDL_BlitSurface(surface_origine, &carre_orig, ecran, &carre_dest);
}




/**
 * \fn static void afficher_tuile(const unsigned int x,
                                  const unsigned int y, const unsigned int id_tuile,
                                  const struct base_donnees* donnees)
 * \brief Affiche une tuile donnee sur un ecran donne a un endroit donne
 *
 * \param[in,out] donnees La base_donnee contenant la surface a modifier
 * \param[in] x Coordonnee horizontale, en pixels, de l'endroit ou
 *              l'on souhaite afficher la tuile
 * \param[in] y Coordonnee verticale, en pixels, de l'endroit ou
 *              l'on souhaite afficher la tuile
 * \param[in] id_tuile L'id de la tuile a afficher
 */
static void afficher_tuile(const unsigned int x,
                           const unsigned int y, const unsigned int id_tuile,
                           const struct base_donnees* donnees)
{
    /*
     * rappel : le 1 en dernier argument est la
     * taille d'une tuile en nombre de cases
     */
    copier_carre(donnees->ecran, x, y, donnees->tuiles,
                 16 * (id_tuile % 10), 16 * (id_tuile / 10), 16);
}








/**
 * \fn static void afficher_ennemis(const struct etat_bataille* bataille,
                                    const unsigned int temps,
                                    const struct base_donnees* donnees)
 * \brief Affiche les sprites des ennemis se trouvant  dans le champ de vision du joueur
 *
 * \param[in] bataille L'etat de la bataille
 * \param[in] temps Le temps ecoule depuis le lancement du jeu
 * \param[in] donnees Une base de donnees correctement remplie
 */

static void afficher_ennemis(const struct etat_bataille* bataille,
                             const unsigned int temps,
                             const struct base_donnees* donnees)
{
    struct ennemi* p_ennemi;
    unsigned int x_j, y_j;
    unsigned char taille_enn;
    unsigned int coord_barre_y;
    char posture;
    rectangle_pour_surface origine;
    rectangle_pour_surface destination;

    x_j = bataille->coord_j_x;
    y_j = bataille->coord_j_y;
    coord_barre_y = POSITION_BARRES_VIE_ENNEMIS_Y;
    p_ennemi = bataille->ennemis.prem;
    while(p_ennemi)
    {
        taille_enn = get_taille(donnees, p_ennemi);
        if(visible_par_joueur(p_ennemi->coord_x, p_ennemi->coord_y, taille_enn,
                              bataille->coord_j_x, bataille->coord_j_y))
        {
            /*
             * meme principe que pour l'affichage du joueur : il faut
             * prendre le sprite qui represente la bonne posture de l'ennemi
             */
            if(p_ennemi->en_mouvement)
            {
                switch((temps / (300 - get_vit_depl(donnees, p_ennemi))) % 4)
                {
                    case 0:
                        /* jambe droite devant */
                        posture = 1;
                        break;
                    case 2:
                        /* jambe gauche devant */
                        posture = 2;
                        break;
                    default:
                        /*
                         * dans tous les autres cas, les deux
                         * jambes sont affiches au meme niveau
                         */
                        posture = 0;
                        break;
                }
            }
            else
                posture = 0;
            copier_carre(donnees->ecran,
                         POSITION_CHAMP_VISION_X + 16 * (CHAMP_VISION_X - x_j + p_ennemi->coord_x),
                         POSITION_CHAMP_VISION_Y + 16 * (CHAMP_VISION_Y - y_j + p_ennemi->coord_y),
                         donnees->sprites_ennemis,
                         taille_enn * 16 * (3 * p_ennemi->orientation + posture),
                         16 * get_loc_sprites(donnees, p_ennemi), 16 * taille_enn);
            /*
             * on se permet d'impliquer l'orientation dans une multiplication
             * afin de se decaler et de prendre le bon sprite.
             * Rappel : HAUT = 0, DROITE = 1, BAS = 2, GAUCHE = 3
             */
        }
        /* affichage du nom de l'ennemi */
        ecrire_sur_surface(donnees->ecran, POSITION_BARRES_VIE_ENNEMIS_X,
                           coord_barre_y - 17,
                           get_nom_ennemi(donnees, p_ennemi),
                           donnees->font_utilisee, 197, 211, 243);
        /* affichage de la barre de vie de l'ennemi */
        /*
         * Rappel : l'image de barre de vie des ennemis fait 150x14 pixels,
         * et l'image de la barre vide est juste au dessous de celle pleine
         */
        /* ===== image de la barre pleine ===== */
        origine.x = 0;
        origine.y = 0;
        origine.w = 150 * p_ennemi->pv / get_pv_max(donnees, p_ennemi);
        origine.h = 14;
        destination.x = POSITION_BARRES_VIE_ENNEMIS_X;
        destination.y = coord_barre_y;
        destination.w = origine.w;
        destination.h = 14;
        SDL_BlitSurface(donnees->barre_vie_ennemis, &origine, donnees->ecran, &destination);
        /* ===== image de la barre vide ===== */
        origine.x += origine.w;
        origine.y = 14;
        origine.w = 150 - origine.w;
        destination.x += destination.w;
        destination.w = origine.w;
        SDL_BlitSurface(donnees->barre_vie_ennemis, &origine, donnees->ecran, &destination);
        coord_barre_y += ESPACEMENT_BARRES_VIE_ENNEMIS;

        p_ennemi = p_ennemi->suiv;
    }
}






/**
 * \fn static void afficher_decor(const struct etat_bataille* bataille, const struct carte_zone* carte,
                                  const struct base_donnees* donnees)
 * \brief Afficher les tuiles du decor se trouvant dans le champ de vision du joueur
 *
 * \param[in] bataille L'etat de la bataille
 * \param[in] carte La carte de la zone
 * \param[in] donnees Une base de donnees correctement remplie
 */
static void afficher_decor(const struct etat_bataille* bataille, const struct carte_zone* carte,
                           const struct base_donnees* donnees)
{
    int x, y;
    unsigned int id_tuile_obtenu;
    int id_tuile_element_destructible;
    struct case_destructible* p_element_destructible;

    /*
     * On va parcourir le rectangle defini par le champ de vision du joueur
     * (dont les dimensions sont donnees en nombre de cases par les constantes
     * que l'on trouve dans les for ci-apres, sachant qu'elles donnent le
     * nombre de cases du joueur au bord du champ de vision) et, a chaque fois,
     * voir si la case ainsi trouvee appartient a la carte ou non. Dans le
     * deuxieme cas, il faudra utiliser la tuile dite "de remplissage
     * d'exterieur", qui est dans la case d'indice 2 du tableau de description
     * des cases constantes de la carte_zone.
     */
    for(y = -CHAMP_VISION_Y;  y <= CHAMP_VISION_Y;  y++)
    {
        for(x = -CHAMP_VISION_X;  x <= CHAMP_VISION_X;  x++)
        {
            id_tuile_element_destructible = -1;
            if(est_dans_carte(x + bataille->coord_j_x, y + bataille->coord_j_y, carte))
            {
                id_tuile_obtenu = get_case_constante_grille(carte,
                            x + bataille->coord_j_x, y + bataille->coord_j_y)->id_tuile;
                p_element_destructible = get_case_destructible(carte,
                                x + bataille->coord_j_x, y + bataille->coord_j_y);
                if(p_element_destructible)
                    id_tuile_element_destructible = p_element_destructible->id_tuile;
            }
            else
                id_tuile_obtenu = get_case_constante_liste_types(carte, 2)->id_tuile;
            /* rappel : 16 est le nombre de pixels de large d'une tuile */
            afficher_tuile(16 * (x + CHAMP_VISION_X) + POSITION_CHAMP_VISION_X,
                           16 * (y + CHAMP_VISION_Y) + POSITION_CHAMP_VISION_Y,
                           id_tuile_obtenu, donnees);
            /*
             * il faut veiller a ne pas essayer d'afficher un
             * element destructible s'il n'y en a pas !
             */
            if(id_tuile_element_destructible >= 0)
            {
                afficher_tuile(16 * (x + CHAMP_VISION_X) + POSITION_CHAMP_VISION_X,
                               16 * (y + CHAMP_VISION_Y) + POSITION_CHAMP_VISION_Y,
                               id_tuile_element_destructible, donnees);
            }
        }
    }
}



/**
 * \fn static void afficher_joueur(const struct etat_bataille* bataille,
                                   const struct resume_saisie* saisie,
                                   const unsigned int temps,
                                   const struct base_donnees* donnees)
 * \brief affiche le joueur au centre du champ de vision
 *
 * \param[in] bataille L'etat de la bataille
 * \param[in] saisie L'adresse d'un resume des touches enfoncees par le joueur
 * \param[in] temps Le temps ecoule depuis le lancement du jeu
 * \param[in] donnees Une base_donnees correctement remplie
 */
static void afficher_joueur(const struct etat_bataille* bataille,
                            const struct resume_saisie* saisie,
                            const unsigned int temps,
                            const struct base_donnees* donnees)
{
    unsigned int num_colonne_sprite;
    unsigned int num_ligne_sprite;
    char posture;

    /*
     * la posture vaut 0 pour l'immobilite, 1 pour la
     * jambe droite devant, et 2 pour la gauche
     */
    if(saisie->orientation == NEUTRE)
        posture = 0;
    else
    {
        /*
         * lorsque le personnage est en mouvement, le but est d'obtenir un
         * cycle "jambe droite, normal, jambe gauche, normal". On utilise
         * donc un modulo 4, puis on ramene les deux "normal" a la meme valeur
         */
        switch((temps / (300 - bataille->stats_temp.vitesse_deplacement)) % 4)
        {
            case 0:
                /* jambe droite devant */
                posture = 1;
                break;
            case 2:
                /* jambe gauche devant */
                posture = 2;
                break;
            default:
                /*
                 * dans tous les autres cas, les deux
                 * jambes sont affiches au meme niveau
                 */
                posture = 0;
                break;
        }
    }
    /*
     * ces formules ne sont pas forcement limpides,
     * mais permettent de trouver le bon sprite
     */
    num_colonne_sprite = 3 * bataille->orientation_j + posture;
    num_ligne_sprite = saisie->direction_tir;
    copier_carre(donnees->ecran,
                 POSITION_CHAMP_VISION_X + 16 * (CHAMP_VISION_X + DECALAGE_X_J),
                 POSITION_CHAMP_VISION_Y + 16 * (CHAMP_VISION_Y + DECALAGE_Y_J),
                 donnees->sprites_joueur,
                 16 * TAILLE_JOUEUR * num_colonne_sprite,
                 16 * TAILLE_JOUEUR * num_ligne_sprite,
                 16 * TAILLE_JOUEUR);
}



/**
 * \fn static void afficher_projectiles(const struct etat_bataille* bataille, const struct base_donnees* donnees)
 * \brief Affiche les sprites des projectiles se trouvant  dans le champ de vision du joueur
 *
 * \param[in] bataille L'etat de la bataille
 * \param[in] donnees Une base de donnees correctement remplie
 */

static void afficher_projectiles(const struct etat_bataille* bataille, const struct base_donnees* donnees)
{
    struct projectile* p_projectile;
    unsigned int x_j, y_j;
    unsigned char taille_proj;

    x_j = bataille->coord_j_x;
    y_j = bataille->coord_j_y;
    p_projectile = bataille->projectiles.prem;
    while(p_projectile)
    {
        taille_proj = get_taille_projectile(donnees, p_projectile);
        if(visible_par_joueur(p_projectile->coord_x, p_projectile->coord_y, taille_proj,
                              bataille->coord_j_x, bataille->coord_j_y))
        {
            copier_carre(donnees->ecran,
                         POSITION_CHAMP_VISION_X + 16 * (CHAMP_VISION_X - x_j + p_projectile->coord_x),
                         POSITION_CHAMP_VISION_Y + 16 * (CHAMP_VISION_Y - y_j + p_projectile->coord_y),
                         donnees->sprites_projectiles,
                         taille_proj * 16 * p_projectile->orientation,
                         16 * get_loc_sprites_projectile(donnees, p_projectile), 16 * taille_proj);
            /*
             * on se permet d'impliquer l'orientation dans une multiplication
             * afin de se decaler et de prendre le bon sprite.
             * Rappel : HAUT = 0, DROITE = 1, BAS = 2, GAUCHE = 3
             */
        }
        p_projectile = p_projectile->suiv;
    }
}



/**
 * \fn static void afficher_barre_vie_joueur(const struct etat_bataille* bataille,
                                      const struct base_donnees* donnees)
 * \brief Affiche la barre de vie du joueur
 *
 * \param[in] bataille L'adresse de l'etat de la bataille en cours
 * \param[in] donnees Une base de donnees correctement remplie
 */
static void afficher_barre_vie_joueur(const struct etat_bataille* bataille, const struct base_donnees* donnees)
{
    rectangle_pour_surface origine;
    rectangle_pour_surface destination;
    char buffer[8];

    /*
     * rappel : l'image de barre de vie du joueur fait 300x28 pixels,
     * et l'image de la barre vide est juste au dessous de celle pleine
     */
    /* ===== image de la barre pleine ===== */
    origine.x = 0;
    origine.y = 0;
    origine.w = 300 * bataille->pv_j / bataille->stats_temp.pv_max;
    origine.h = 28;
    destination.x = POSITION_BARRE_VIE_JOUEUR_X;
    destination.y = POSITION_BARRE_VIE_JOUEUR_Y;
    destination.w = origine.w;
    destination.h = 28;
    SDL_BlitSurface(donnees->barre_vie_joueur, &origine, donnees->ecran, &destination);
    /* ===== image de la barre vide ===== */
    origine.x += origine.w;
    origine.y = 28;
    origine.w = 300 - origine.w;
    destination.x += destination.w;
    destination.w = origine.w;
    SDL_BlitSurface(donnees->barre_vie_joueur, &origine, donnees->ecran, &destination);
    sprintf(buffer, "%u", bataille->pv_j);
    ecrire_sur_surface(donnees->ecran, POSITION_POINTS_VIE_JOUEUR_X,
                       POSITION_POINTS_VIE_JOUEUR_Y, buffer, donnees->font_utilisee, 255, 255, 255);
}



/**
 * \fn static void afficher_barre_charge(const struct etat_bataille* bataille,
                                         const struct base_donnees* donnees)
 * \brief Affiche la barre de charge du joueur
 *
 * \param[in] bataille L'adresse de l'etat de la bataille en cours
 * \param[in] donnees Une base de donnees correctement remplie
 */
static void afficher_barre_charge(const struct etat_bataille* bataille, const struct base_donnees* donnees)
{
    rectangle_pour_surface origine;
    rectangle_pour_surface destination;

    /*
     * meme principe que pour la barre de vie
     */
    /* ===== image de la barre pleine ===== */
    origine.x = 0;
    origine.y = 0;
    if((origine.w = 150 * bataille->score_charge_j / SEUIL_CHARGE) > 150)
        origine.w = 150;
    origine.h = 14;
    destination.x = POSITION_BARRE_CHARGE_X;
    destination.y = POSITION_BARRE_CHARGE_Y;
    destination.w = origine.w;
    destination.h = 14;
    SDL_BlitSurface(donnees->barre_charge, &origine, donnees->ecran, &destination);
    /* ===== image de la barre vide ===== */
    origine.x += origine.w;
    origine.y = 14;
    origine.w = 150 - origine.w;
    destination.x += destination.w;
    destination.w = origine.w;
    SDL_BlitSurface(donnees->barre_charge, &origine, donnees->ecran, &destination);
}



/**
 * \fn static void afficher_raccords(const struct etat_exploration* exploration,
                                     const unsigned char x,
                                     const unsigned char y,
                                     const struct zone* p_zone,
                                     const struct base_donnees* donnees)
 * \brief Affiche les eventuels raccords autour
 *        d'une zone dans la carte d'une region
 *
 * \param[in] exploration L'adresse de l'etat de l'exploration en cours
 * \param[in] x La coordonnee horizontale de la zone concernee
 * \param[in] y La coordonnee verticale de la zone concernee
 * \param[in] p_zone L'adresse de la zone concernee
 * \param[in] donnees L'adresse d'une base_donnees correctement remplie
 */
static void afficher_raccords(const struct etat_exploration* exploration,
                              const unsigned char x,
                              const unsigned char y,
                              const struct zone* p_zone,
                              const struct base_donnees* donnees)
{
    if(p_zone->raccords[HAUT])
    {
        copier_carre(donnees->ecran,
                     POSITION_CARTE_REGION_X + (4 * x + 1) * UNITE_CARTE_REGION,
                     POSITION_CARTE_REGION_Y + (4 * y - 1) * UNITE_CARTE_REGION,
                     donnees->zones_carte_region,
                     5, 0,
                     UNITE_CARTE_REGION);
    }
    if(p_zone->raccords[DROITE])
    {
        copier_carre(donnees->ecran,
                     POSITION_CARTE_REGION_X + (4 * x + 3) * UNITE_CARTE_REGION,
                     POSITION_CARTE_REGION_Y + (4 * y + 1) * UNITE_CARTE_REGION,
                     donnees->zones_carte_region,
                     5, 0,
                     UNITE_CARTE_REGION);
    }
    if(p_zone->raccords[BAS])
    {
        copier_carre(donnees->ecran,
                     POSITION_CARTE_REGION_X + (4 * x + 1) * UNITE_CARTE_REGION,
                     POSITION_CARTE_REGION_Y + (4 * y + 3) * UNITE_CARTE_REGION,
                     donnees->zones_carte_region,
                     5, 0,
                     UNITE_CARTE_REGION);
    }
    if(p_zone->raccords[GAUCHE])
    {
        copier_carre(donnees->ecran,
                     POSITION_CARTE_REGION_X + (4 * x - 1) * UNITE_CARTE_REGION,
                     POSITION_CARTE_REGION_Y + (4 * y + 1) * UNITE_CARTE_REGION,
                     donnees->zones_carte_region,
                     5, 0,
                     UNITE_CARTE_REGION);
    }
}



/**
 * \fn static void mettre_fleche(char chaine[])
 * \brief Rallonge une chaine de caracteres en rajoutant, a un emplacement
 *        precis, une fleche suivie d'un espace
 *
 * \param[in,out] chaine Une chaine de caracteres
 *
 * L'espace entre la fin de la chaine et la
 * fleche sera complete avec des espaces.
 */
static void mettre_fleche(char chaine[])
{
    sprintf(chaine + 29, "--> ");
}



/**
 * \fn static void mettre_difference(char chaine[], const int difference)
 * \brief Affiche "(+n)" pour n > 0, "(-n)" si n < 0, et rien si n est nul
 * et ce a un endroit precis d'une chaine de caracteres
 *
 * \param[in,out] chaine Une chaine de caracteres
 * \param[in] difference Le nombre a utiliser
 */
static void mettre_difference(char chaine[], const int difference)
{
    if(difference < 0)
        sprintf(chaine + 38, "(%d)", difference);
    else
        if(difference != 0)
            sprintf(chaine + 38, "(+%d)", difference);
}




/**
 * \fn static void afficher_objets(const struct etat_partie* partie,
                                   const struct base_donnees* donnees)
 * \brief Afficher F1, F2 et F3 suivis des noms des objets qui peuvent
 *        etre utilises avec chacune de ces touches
 *
 * \param[in] partie L'adresse de l'etat de la partie
 * \param[in] donnees L'adresse d'une base de donnees correctement remplie
 */
static void afficher_objets(const struct etat_partie* partie,
                     const struct base_donnees* donnees)
{
    char buffer[64];
    int i;
    unsigned int pos_y;

    pos_y = POSITION_OBJETS_Y;
    for(i = 0;  i < 3;  i++)
    {
        if(partie->objets_utilisables[i] == VIDE)
            sprintf(buffer, "F%d : <Vide>", i + 1);
        else
            sprintf(buffer, "F%d : %s", i + 1, get_nom_objet(donnees, partie->objets_utilisables[i]));
        ecrire_sur_surface(donnees->ecran, POSITION_OBJETS_X, pos_y,
                           buffer, donnees->font_utilisee, 255, 255, 255);
        pos_y += 15;
    }
}



/**
 * \fn static char get_statut_zone_exploration(struct zone* zone_exploration,
                                               const struct etat_partie* partie)
 * \brief Permet de savoir si une zone vient d'etre exploree,
 *        a deja ete exploree, ou n'a jamais ete exploree
 *
 * \param[in] zone_exploration Un pointeur vers la zone concernee
 * \param[in] partie L'adresse de l'etat de la partie
 * \return EXPLOREE si la zone vient d'etre exploree,\n
 *         DEJA_VUE si la zone a ete exploree mais pas recemment,\n
 *         JAMAIS vue sinon
 */
static char get_statut_zone_exploration(struct zone* zone_exploration,
                                        const struct etat_partie* partie)
{
    if(zone_exploration->exploree)
    {
        /* zones qui viennent d'etre explorees */
        return EXPLOREE;
    }
    if(voir_si_zone_est_terminee(partie,
                                 get_region_partie(partie),
                                 zone_exploration->id_zone))
    {
        /*
         * zones ayant ete explorees
         * lors d'une autre exploration
         */
         return DEJA_VUE;
    }
    /* zones jamais explorees */
    return JAMAIS_VUE;
}



/**
 * \fn static void afficher_legende_carte_region(const struct base_donnees* donnees)
 * \brief Affiche les instructions sur la carte de region
 *
 * \param[in] donnees L'adresse d'une base de donnees correctement remplie
 */
static void afficher_legende_carte_region(const struct base_donnees* donnees)
{
    ecrire_sur_surface(donnees->ecran,
                       POSITION_LEGENDE_REGION_X,
                       POSITION_LEGENDE_REGION_Y,
                       "Zone accessible",
                       donnees->font_utilisee,
                       70, 70, 140);
    copier_carre(donnees->ecran,
                 POSITION_LEGENDE_REGION_X + DECALAGE_LEGENDE_REGION - 115,
                 POSITION_LEGENDE_REGION_Y - 6,
                 donnees->zones_carte_region,
                 9 * UNITE_CARTE_REGION, 0,
                 3 * UNITE_CARTE_REGION);
    ecrire_sur_surface(donnees->ecran,
                       POSITION_LEGENDE_REGION_X + DECALAGE_LEGENDE_REGION,
                       POSITION_LEGENDE_REGION_Y,
                       "Zone exploree",
                       donnees->font_utilisee,
                       70, 70, 140);
    copier_carre(donnees->ecran,
                 POSITION_LEGENDE_REGION_X + 2 * DECALAGE_LEGENDE_REGION - 115,
                 POSITION_LEGENDE_REGION_Y - 6,
                 donnees->zones_carte_region,
                 3 * UNITE_CARTE_REGION * EXPLOREE, 0,
                 3 * UNITE_CARTE_REGION);
    ecrire_sur_surface(donnees->ecran,
                       POSITION_LEGENDE_REGION_X + 2 * DECALAGE_LEGENDE_REGION,
                       POSITION_LEGENDE_REGION_Y,
                       "Zone deja vue",
                       donnees->font_utilisee,
                       70, 70, 140);
    copier_carre(donnees->ecran,
                 POSITION_LEGENDE_REGION_X + 3 * DECALAGE_LEGENDE_REGION - 115,
                 POSITION_LEGENDE_REGION_Y - 6,
                 donnees->zones_carte_region,
                 3 * UNITE_CARTE_REGION * DEJA_VUE, 0,
                 3 * UNITE_CARTE_REGION);
    ecrire_sur_surface(donnees->ecran,
                       POSITION_LEGENDE_REGION_X,
                       POSITION_LEGENDE_REGION_Y + 40,
                       "Zones jamais vue",
                       donnees->font_utilisee,
                       70, 70, 140);
    copier_carre(donnees->ecran,
                 POSITION_LEGENDE_REGION_X + DECALAGE_LEGENDE_REGION - 115,
                 POSITION_LEGENDE_REGION_Y + 34,
                 donnees->zones_carte_region,
                 3 * UNITE_CARTE_REGION * JAMAIS_VUE, 0,
                 3 * UNITE_CARTE_REGION);
    ecrire_sur_surface(donnees->ecran,
                       POSITION_LEGENDE_REGION_X + DECALAGE_LEGENDE_REGION,
                       POSITION_LEGENDE_REGION_Y + 40,
                       "Votre position",
                       donnees->font_utilisee,
                       70, 70, 140);
    copier_carre(donnees->ecran,
                 POSITION_LEGENDE_REGION_X + 2 * DECALAGE_LEGENDE_REGION - 115,
                 POSITION_LEGENDE_REGION_Y + 34,
                 donnees->zones_carte_region,
                 12 * UNITE_CARTE_REGION, 0,
                 3 * UNITE_CARTE_REGION);
    ecrire_sur_surface(donnees->ecran,
                       POSITION_EXPLICATIONS_REGION_X,
                       POSITION_EXPLICATIONS_REGION_Y,
                       "Cliquez sur une region accessible ou appuyez"
                       " sur Echap pour acceder au menu",
                       donnees->font_utilisee,
                       90, 90, 180);
}



void remplir_rectangle_surface(surface_jeu* surface,
                               rectangle_pour_surface* rect,
                               const Uint32 couleur)
{
    SDL_FillRect(surface, rect, couleur);
}



void rafraichir_ecran(surface_jeu* ecran)
{
    SDL_Flip(ecran);
}



void afficher_image(surface_jeu* ecran, surface_jeu* image,
                    const unsigned int x,
                    const unsigned int y)
{
    rectangle_pour_surface destination;

    destination.x = x;
    destination.y = y;
    SDL_BlitSurface(image, NULL, ecran, &destination);
}



void ecrire_sur_surface(surface_jeu* surface,
                        const unsigned int pos_x, const unsigned int pos_y,
                        const char* texte, font* font_a_utiliser,
                        const unsigned char rouge, const unsigned char vert,
                        const unsigned char bleu)
{
    surface_jeu* surface_intermediaire;
    couleur_pour_surface couleur;
    rectangle_pour_surface zone_destination;

    couleur.r = rouge;
    couleur.g = vert;
    couleur.b = bleu;
    zone_destination.x = pos_x;
    zone_destination.y = pos_y;
    surface_intermediaire = TTF_RenderText_Solid(font_a_utiliser, texte, couleur);
    SDL_BlitSurface(surface_intermediaire, NULL, surface, &zone_destination);
    detruire_surface(surface_intermediaire);
}



surface_jeu* creer_ecran(const unsigned int dim_x, const unsigned int dim_y)
{
    surface_jeu* ecran;

    if(!(ecran = SDL_SetVideoMode(dim_x, dim_y, BPP, SDL_HWSURFACE | SDL_DOUBLEBUF)))
        exit(EXIT_FAILURE);
    /* nom de la fenetre */
    SDL_WM_SetCaption("Peteux 3", "Peteux 3");

    return ecran;
}



void detruire_surface(surface_jeu* surface)
{
    SDL_FreeSurface(surface);
}



surface_jeu* charger_image(const char* nom_fichier)
{
    surface_jeu* image;
    surface_jeu* image_optimisee;
    int couleur_transparence;

    printf("Chargement de l'image %s...\n", nom_fichier);
    if((image = SDL_LoadBMP(nom_fichier)) == NULL)
    {
        printf("Erreur lors de l'ouverture\n");
        exit(EXIT_FAILURE);
    }
    else
    {
        printf("Fichier ouvert. Optimisation...\n");
        image_optimisee = SDL_DisplayFormat(image);
        if(!image_optimisee)
        {
            printf("Echec\n");
            exit(EXIT_FAILURE);
        }
        detruire_surface(image);
        couleur_transparence = SDL_MapRGB(image_optimisee->format, 0x00, 0xFF, 0xFF);
        SDL_SetColorKey(image_optimisee, SDL_RLEACCEL | SDL_SRCCOLORKEY, couleur_transparence);
    }
    printf("Termine\n");

    return image_optimisee;
}



font* ouvrir_font(const char* nom_font, const unsigned char taille,
                  const char silencieux)
{
    font* font_ouverte;

    font_ouverte = NULL;
    if(!silencieux)
        printf("Chargement de la font %s (taille %u)...\n", nom_font, taille);
    font_ouverte = TTF_OpenFont(nom_font, taille);
    if(!font_ouverte)
    {
        if(!silencieux)
            printf("Erreur lors de l'ouverture\n");
        exit(EXIT_FAILURE);
    }
    if(!silencieux)
        printf("Termine\n");

    return font_ouverte;
}



void fermer_font(font* font_a_fermer)
{
    TTF_CloseFont(font_a_fermer);
}



void afficher_bataille(const struct etat_bataille* bataille,
                       const struct etat_partie* partie,
                       const struct carte_zone* carte,
                       const struct resume_saisie* saisie,
                       const unsigned int temps,
                       const struct base_donnees* donnees)
{
    /* effacage de l'ecran, peut-etre temporaire */
    remplir_rectangle_surface(donnees->ecran, NULL, 0x000000);
    afficher_decor(bataille, carte, donnees);
    afficher_ennemis(bataille, temps, donnees);
    afficher_joueur(bataille, saisie, temps, donnees);
    afficher_projectiles(bataille, donnees);
    afficher_barre_vie_joueur(bataille, donnees);
    afficher_barre_charge(bataille, donnees);
    afficher_objets(partie, donnees);



    /* affichage des coordonnees du joueur */
    /*
    char buffer[1048];

    sprintf(buffer, "(%u ; %u)", bataille->coord_j_x, bataille->coord_j_y);
    ecrire_sur_surface(donnees->ecran, 80, 80, buffer, donnees->font_utilisee, 255, 255, 255);
    */
}



void afficher_carte_region(const struct etat_partie* partie,
                           const struct etat_exploration* exploration,
                           struct base_donnees* donnees)
{
    int i, j;
    struct zone* p_zone;
    char statut_zone;
    rectangle_pour_surface rectangle;

    remplir_rectangle_surface(donnees->ecran, NULL, 0xdddddd);
    rectangle.w = 35 * UNITE_CARTE_REGION + 18;
    rectangle.h = 35 * UNITE_CARTE_REGION + 18;
    rectangle.x = POSITION_CARTE_REGION_X - 9;
    rectangle.y = POSITION_CARTE_REGION_Y - 9;
    remplir_rectangle_surface(donnees->ecran, &rectangle, 0x7A7A7A);
    charger_font_titres(donnees);
    ecrire_sur_surface(donnees->ecran,
                       POSITION_NOM_REGION_X, POSITION_NOM_REGION_Y,
                       exploration->nom_region, donnees->font_utilisee,
                       80, 80, 255);
    charger_font_defaut(donnees);
    for(j = 0;  j < 9;  j++)
        for(i = 0;  i < 9;  i++)
        {
            p_zone = get_zone_exploration(exploration, i, j);
            /*
             * bien evidemment, il ne faut pas tenter d'afficher
             * une zone si l'emplacement est vide
             */
            if(p_zone)
            {
                statut_zone = get_statut_zone_exploration(p_zone, partie);
                /*
                 * les zones sont representees par des carres de 3 unites de
                 * cotes, et les raccords entre elles sont des carres
                 * de 1 unite de cote, il faut donc se decaler
                 * de 4 unites a chaque fois
                 */
                copier_carre(donnees->ecran,
                             POSITION_CARTE_REGION_X + 4 * UNITE_CARTE_REGION * i,
                             POSITION_CARTE_REGION_Y + 4 * UNITE_CARTE_REGION * j,
                             donnees->zones_carte_region,
                             3 * UNITE_CARTE_REGION * statut_zone, 0,
                             3 * UNITE_CARTE_REGION);
                if(p_zone->id_zone == get_zone_partie(partie))
                {
                    /* affichage de la position du joueur */
                    copier_carre(donnees->ecran,
                                 POSITION_CARTE_REGION_X + 4 * UNITE_CARTE_REGION * i,
                                 POSITION_CARTE_REGION_Y + 4 * UNITE_CARTE_REGION * j,
                                 donnees->zones_carte_region,
                                 12 * UNITE_CARTE_REGION, 0,
                                 3 * UNITE_CARTE_REGION);
                }
                if(voir_si_zone_accessible(exploration, i, j))
                {
                    /* on indique que la zone est accessible */
                    copier_carre(donnees->ecran,
                                 POSITION_CARTE_REGION_X + 4 * UNITE_CARTE_REGION * i,
                                 POSITION_CARTE_REGION_Y + 4 * UNITE_CARTE_REGION * j,
                                 donnees->zones_carte_region,
                                 9 * UNITE_CARTE_REGION, 0,
                                 3 * UNITE_CARTE_REGION);
                }
                afficher_raccords(exploration, i, j, p_zone, donnees);
            }
        }
    afficher_legende_carte_region(donnees);
    rafraichir_ecran(donnees->ecran);
}



void afficher_carte_monde(const struct tab_regions_accessibles* accessibles,
                          struct base_donnees* donnees)
{
    int i;
    unsigned int id_region;
    unsigned int x_region, y_region;
    const char* nom_region;

    remplir_rectangle_surface(donnees->ecran, NULL, 0xdedede);
    charger_font_titres(donnees);
    ecrire_sur_surface(donnees->ecran,
                       POSITION_TITRE_MONDE_X, POSITION_TITRE_MONDE_Y,
                       "Carte du Monde", donnees->font_utilisee,
                       80, 80, 255);
    charger_font_defaut(donnees);
    for(i = 0;  i < accessibles->nb_elements;  i++)
    {
        id_region = accessibles->tab[i];
        nom_region = get_tout_region(donnees, id_region, &x_region, &y_region);
        x_region += POSITION_CARTE_MONDE_X;
        y_region += POSITION_CARTE_MONDE_Y;
        ecrire_sur_surface(donnees->ecran, x_region, y_region,
                           nom_region,
                           donnees->font_utilisee,
                           128, 128, 128);
    }
    ecrire_sur_surface(donnees->ecran, 45, 600,
                       "Cliquez sur une region ou appuyez sur Echap pour acceder au menu",
                       donnees->font_utilisee,
                       90, 90, 180);
    rafraichir_ecran(donnees->ecran);
}



void afficher_aide(surface_jeu* ecran, font* font_aide)
{
    surface_jeu* capture_ecran;
    struct resume_saisie saisie;
    rectangle_pour_surface rectangle;

    /*
     * pour ne pas surcharger la memoire, on ne charge pas la
     * capture d'ecran de l'aide dans la base de donnees. On la charge
     * uniquement lorsque l'aide doit etre affichee, puis on la detruit
     */
    capture_ecran = charger_image("donnees/images/aide.bmp");

    init_resume_saisie(&saisie);
    do
    {
        afficher_image(ecran, capture_ecran, 0, 0);
        ecrire_sur_surface(ecran, 15, 520, "Deplacement : fleches",
                           font_aide, 100, 100, 255);
        ecrire_sur_surface(ecran, 15, 545, "Tir : Z (haut), D (droite), S (bas), Q (gauche)",
                           font_aide, 100, 100, 255);
        ecrire_sur_surface(ecran, 15, 570, "Pour pouvoir tirer, il faut que la barre de charge soit pleine",
                           font_aide, 100, 100, 255);
        ecrire_sur_surface(ecran, 15, 595, "Utilisation d'objets : F1, F2, F3",
                           font_aide, 100, 100, 255);
        ecrire_sur_surface(ecran, 15, 620, "Pause : Echap",
                           font_aide, 100, 100, 255);
        ecrire_sur_surface(ecran, 15, 645, "Dans les menus, Backspace peut etre utilise pour revenir en arriere",
                           font_aide, 100, 100, 255);
        rafraichir_ecran(ecran);
        recolter_evenements(&saisie);
    } while(!saisie.entree);

    rectangle.x = 0;
    rectangle.y = 0;
    rectangle.w = DIM_ECRAN_X;
    rectangle.h = DIM_ECRAN_Y;
    remplir_rectangle_surface(ecran, &rectangle, 0x000000);
    rafraichir_ecran(ecran);

    detruire_surface(capture_ecran);
}



/* ===== Mode texte (pour menus etc) ===== */

void demarrer_texte(void)
{
    if(!initscr())
        exit(EXIT_FAILURE);
    noecho();
    /*
     * rappel curs_set :
     * 0 -> invisible
     * 1 -> normal
     * 2 -> tres visible
     */
    curs_set(0);
}



fenetre_texte* ouvrir_fenetre_texte(const unsigned int dim_x,
                                    const unsigned int dim_y,
                                    const unsigned int pos_x,
                                    const unsigned int pos_y)
{
    WINDOW *fenetre;

	fenetre = newwin(dim_y, dim_x, pos_y, pos_x);
	box(fenetre, 0, 0);
	keypad(fenetre, VRAI);
    wrefresh(fenetre);

	return fenetre;
}



void fermer_fenetre_texte(fenetre_texte* fenetre)
{
    wborder(fenetre, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
    werase(fenetre);
	wrefresh(fenetre);
    delwin(fenetre);
}



void arreter_texte(void)
{
    erase();
    refresh();
    endwin();
}



void vider_fenetre_texte(fenetre_texte* fenetre)
{
    werase(fenetre);
    box(fenetre, 0, 0);
    wmove(fenetre, 0, 0);
}



void afficher_titre_fenetre(fenetre_texte* fenetre, const char* titre)
{
    unsigned int dim_x;

    dim_x = getmaxx(fenetre);
    wattron(fenetre, A_UNDERLINE | A_BOLD);
    mvwprintw(fenetre, 0, (dim_x - strlen(titre)) / 2, "%s", titre);
    wattroff(fenetre, A_UNDERLINE | A_BOLD);
}



void afficher_dans_boite(fenetre_texte* fenetre,
                         unsigned int* pos_y,
                         char* texte)
{
    unsigned int largeur_fenetre, hauteur_fenetre;

    getmaxyx(fenetre, hauteur_fenetre, largeur_fenetre);
    if(strlen(texte) > largeur_fenetre - 4)
        texte[largeur_fenetre - 4] = '\0';

    if(*pos_y > hauteur_fenetre - 2)
    {
        mvwprintw(fenetre, *pos_y, 2, "Suite : appuyez sur Entree", texte);
        attendre_entree(fenetre);
        wclear(fenetre);
        box(fenetre, 0, 0);
        wrefresh(fenetre);
        *pos_y = 2;
    }
    mvwprintw(fenetre, *pos_y, 2, "%s", texte);
    *pos_y = *pos_y + 1;
}



void afficher_stats_objet(fenetre_texte* fenetre,
                          unsigned int* pos_y,
                          const unsigned int id_objet,
                          const struct base_donnees* donnees)
{
    char buffer[128];
    unsigned char id_projectile;

    wattron(fenetre, A_UNDERLINE);
    afficher_dans_boite(fenetre, pos_y, get_nom_objet(donnees, id_objet));
    wattroff(fenetre, A_UNDERLINE);
    sprintf(buffer, "Points de vie :        %u", get_pv_objet(donnees, id_objet));
    afficher_dans_boite(fenetre, pos_y, buffer);
    sprintf(buffer, "Puissance :            %u", get_puissance_objet(donnees, id_objet));
    afficher_dans_boite(fenetre, pos_y, buffer);
    sprintf(buffer, "Vitesse deplacement :  %u", get_vitesse_deplacement_objet(donnees, id_objet));
    afficher_dans_boite(fenetre, pos_y, buffer);
    sprintf(buffer, "Vitesse charge :       %u", get_vitesse_charge_objet(donnees, id_objet));
    afficher_dans_boite(fenetre, pos_y, buffer);
    if(get_type_objet(donnees, id_objet) == ARME)
    {
        id_projectile = get_id_projectile_objet(donnees, id_objet);
        sprintf(buffer, "Vitesse projectile :   %u",
                get_vitesse_deplacement_projectile_par_id(donnees, id_projectile));
        afficher_dans_boite(fenetre, pos_y, buffer);
        sprintf(buffer, "Taille projectile :    %u",
                get_taille_projectile_par_id(donnees, id_projectile));
        afficher_dans_boite(fenetre, pos_y, buffer);
    }
}



void afficher_evolution_stats(fenetre_texte* fenetre, unsigned int* pos_y,
                              const struct etat_partie* partie,
                              const unsigned int id_objet,
                              const char type_objet,
                              const struct base_donnees* donnees)
{
    char buffer[128];
    unsigned char id_proj_actuel;
    unsigned char id_proj_nouveau;
    unsigned int valeur_champ_stats;
    unsigned int id_objet_actuel;
    int difference;

    /*
     * a chaque fois, on affiche l'ancienne
     * valeur d'un champ des stats, une
     * fleche, puis la nouvelle valeur.
     * Attention au cas particulier du nom : les get des objets pour les stats
     * renvoient 0 pour un champ vide, mais il faut eviter de faire un print
     * pour le nom avec une chaine NULL !
     */
    id_objet_actuel = get_equipement(partie, type_objet);
    wattron(fenetre, A_BOLD);
    if(id_objet_actuel == VIDE)
        sprintf(buffer, "<Rien>                        ");
    else
        sprintf(buffer, "%s                             ",
                get_nom_objet(donnees, id_objet_actuel));
    mettre_fleche(buffer);
    if(id_objet == VIDE)
        sprintf(buffer + 33, "<Rien>                        ");
    else
        sprintf(buffer + 33, "%s                             ",
                get_nom_objet(donnees, id_objet));
    afficher_dans_boite(fenetre, pos_y, buffer);
    wattroff(fenetre, A_BOLD);

    valeur_champ_stats = calculer_somme_stats(partie, POINTS_VIE, donnees);
    difference = get_pv_objet(donnees, id_objet)
                 - get_pv_objet(donnees, id_objet_actuel);
    sprintf(buffer, "Pts vie : %u                  ", valeur_champ_stats);
    mettre_fleche(buffer);
    sprintf(buffer + 33, "%u    ", valeur_champ_stats + difference);
    mettre_difference(buffer, difference);
    afficher_dans_boite(fenetre, pos_y, buffer);

    valeur_champ_stats = calculer_somme_stats(partie, PUISSANCE, donnees);
    difference = get_puissance_objet(donnees, id_objet)
                 - get_puissance_objet(donnees, id_objet_actuel);
    sprintf(buffer, "Puissan : %u                  ", valeur_champ_stats);
    mettre_fleche(buffer);
    sprintf(buffer + 33, "%u    ", valeur_champ_stats + difference);
    mettre_difference(buffer, difference);
    afficher_dans_boite(fenetre, pos_y, buffer);

    valeur_champ_stats = calculer_somme_stats(partie, VITESSE_DEPLACEMENT, donnees);
    difference = get_vitesse_deplacement_objet(donnees, id_objet)
                 - get_vitesse_deplacement_objet(donnees, id_objet_actuel);
    sprintf(buffer, "Vit dep : %u                  ", valeur_champ_stats);
    mettre_fleche(buffer);
    sprintf(buffer + 33, "%u    ", valeur_champ_stats + difference);
    mettre_difference(buffer, difference);
    afficher_dans_boite(fenetre, pos_y, buffer);

    valeur_champ_stats = calculer_somme_stats(partie, VITESSE_CHARGE, donnees);
    difference = get_vitesse_charge_objet(donnees, id_objet)
                 - get_vitesse_charge_objet(donnees, id_objet_actuel);
    sprintf(buffer, "Vit cha : %u                  ", valeur_champ_stats);
    mettre_fleche(buffer);
    sprintf(buffer + 33, "%u    ", valeur_champ_stats + difference);
    mettre_difference(buffer, difference);
    afficher_dans_boite(fenetre, pos_y, buffer);

    if(type_objet == ARME)
    {
        id_proj_actuel = get_id_projectile_objet(donnees, id_objet_actuel);
        id_proj_nouveau = get_id_projectile_objet(donnees, id_objet);


        sprintf(buffer, "Vit pro : %u                  ",
                get_vitesse_deplacement_projectile_par_id(donnees, id_proj_actuel));
        mettre_fleche(buffer);
        sprintf(buffer + 33, "%u",
                get_vitesse_deplacement_projectile_par_id(donnees, id_proj_nouveau));
        afficher_dans_boite(fenetre, pos_y, buffer);

        sprintf(buffer, "Tai pro : %u                  ",
                get_taille_projectile_par_id(donnees, id_proj_actuel));
        mettre_fleche(buffer);
        sprintf(buffer + 33, "%u",
                get_taille_projectile_par_id(donnees, id_proj_nouveau));
        afficher_dans_boite(fenetre, pos_y, buffer);
    }
}



void afficher_quantite(fenetre_texte* fenetre,
                       unsigned int* pos_y,
                       const struct etat_partie* partie,
                       const unsigned int id_objet)
{
    char buffer[32];

    sprintf(buffer, "Quantite : %u", get_quantite_possedee(partie, id_objet));
    afficher_dans_boite(fenetre, pos_y, buffer);
}



fenetre_texte* afficher_stats_joueur(const unsigned int x_fenetre,
                                     const unsigned int y_fenetre,
                                     const struct etat_partie* partie,
                                     const struct base_donnees* donnees)
{
    fenetre_texte* fenetre;
    char buffer[128];
    unsigned int pos_y;
    unsigned char niveau;

    fenetre = ouvrir_fenetre_texte(59, 12, x_fenetre, y_fenetre);

    pos_y = 1;
    sprintf(buffer, "%s                                ", partie->nom);
    niveau = calculer_niveau(partie->experience, donnees);
    sprintf(buffer + 32, "Niveau %u", niveau);
    afficher_dans_boite(fenetre, &pos_y, buffer);
    sprintf(buffer, "Experience : %u         ", partie->experience);
    sprintf(buffer + 23, "Niveau suivant dans %u points",
            donner_palier_suivant(niveau, donnees) - partie->experience);
    afficher_dans_boite(fenetre, &pos_y, buffer);
    pos_y++;
    afficher_dans_boite(fenetre, &pos_y, "          Sans equipement   Avec equipement");
    sprintf(buffer, "Pts vie :       %u                 ", get_pv_max_perm(partie));
    sprintf(buffer + 34, "%u", calculer_somme_stats(partie, POINTS_VIE, donnees));
    afficher_dans_boite(fenetre, &pos_y, buffer);
    sprintf(buffer, "Vit dep :       %u                 ", get_vitesse_deplacement_perm(partie));
    sprintf(buffer + 34, "%u", calculer_somme_stats(partie, VITESSE_DEPLACEMENT, donnees));
    afficher_dans_boite(fenetre, &pos_y, buffer);
    sprintf(buffer, "Puissan :       %u                 ", get_puissance_perm(partie));
    sprintf(buffer + 34, "%u", calculer_somme_stats(partie, PUISSANCE, donnees));
    afficher_dans_boite(fenetre, &pos_y, buffer);
    sprintf(buffer, "Vit cha :       %u                 ", get_vitesse_charge_perm(partie));
    sprintf(buffer + 34, "%u", calculer_somme_stats(partie, VITESSE_CHARGE, donnees));
    afficher_dans_boite(fenetre, &pos_y, buffer);
    pos_y++;
    sprintf(buffer, "Argent : %u", partie->argent);
    afficher_dans_boite(fenetre, &pos_y, buffer);

    wrefresh(fenetre);

    return fenetre;
}








